package com.junsi.common.utils;


import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MappingIterator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.databind.type.TypeFactory;

public class JsonUtil {
	private final static ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().serializationInclusion(JsonInclude.Include.NON_NULL).build().configure(SerializationFeature.INDENT_OUTPUT, true);
	private final static JsonEncoding encoding = JsonEncoding.UTF8;

	public static String json(Object object) throws IOException {
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		JsonGenerator generator = objectMapper.getFactory().createGenerator(bos, encoding);
		objectMapper.writeValue(generator, object);
		generator.flush();
		return new String(bos.toByteArray(), encoding.getJavaName());
	}

	public static <T> T object(String json, Class<T> valueType) throws IOException {
		objectMapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
		return objectMapper.readValue(json, valueType);
	}

	public static <T> List<T> list(String json, Class<T> valueType) throws IOException {
		JsonParser parser = objectMapper.getFactory().createParser(json);
		CollectionType type = TypeFactory.defaultInstance().constructCollectionType(ArrayList.class, valueType);
		MappingIterator<List<T>> it = objectMapper.readValues(parser, type);
		if (it.hasNext()) {
			return it.next();
		}
		return new ArrayList<T>();
	}
	
	public static String getJsonByUserNames(List<?> list,String...names){
		StringBuilder json = new StringBuilder();     
        json.append("[");     
       if (list != null && list.size() > 0) {     
           for (Object obj : list) {     
                json.append(objectToJson(obj,names));     
                json.append(",");     
            }     
            json.setCharAt(json.length() - 1, ']');     
        } else {     
            json.append("]");     
        }     
       return json.toString(); 
	}
	 public static String beanToJson(Object bean, String[] names) {     
         StringBuilder json = new StringBuilder();     
         json.append("{");     
         PropertyDescriptor[] props = null;     
        try {     
             props = Introspector.getBeanInfo(bean.getClass(), Object.class)     
                     .getPropertyDescriptors();     
         } catch (IntrospectionException e) {     
         }     
        if (props != null) {     
            for (int i = 0; i < props.length; i++) {     
                try {    
                     String name = objectToJson(props[i].getName()); 
					if (names == null) {
						String value = objectToJson(props[i].getReadMethod()
								.invoke(bean));
						json.append(name);
						json.append(":");
						json.append(value);
						json.append(",");
					} else {
						for (String username : names) {
							if (username.equals(name.replace("\"", ""))) {
								String value = objectToJson(props[i]
										.getReadMethod().invoke(bean));
								json.append(name);
								json.append(":");
								json.append(value);
								json.append(",");
							}
						}
					}
                 } catch (Exception e) {     
                 }     
             }     
             json.setCharAt(json.length() - 1, '}');     
         } else {     
             json.append("}");     
         }     
        return json.toString();     
     }   
	 public static String objectToJson(Object object,String...names) {     
         StringBuilder json = new StringBuilder();     
        if (object == null) {     
             json.append("\"\"");     
         } else if (object instanceof String || object instanceof Integer) {   
             json.append("\"").append(object.toString()).append("\"");    
         } else {     
             json.append(beanToJson(object,names));     
         }     
        return json.toString();     
     }  
	 
	 /**  对象转json 标准
	 * @param obj
	 * @return
	 */
	public static String object2json(Object obj) {
		    StringBuilder json = new StringBuilder();
		    if (obj == null) {
		      json.append("\"\"");
		    } else if (obj instanceof String || obj instanceof Integer || obj instanceof Float
		        || obj instanceof Boolean || obj instanceof Short || obj instanceof Double
		        || obj instanceof Long || obj instanceof BigDecimal || obj instanceof BigInteger
		        || obj instanceof Byte||obj instanceof Date) {	    	
		      json.append("\"").append(string2json(obj.toString())).append("\"");
		    } else if (obj instanceof Object[]) {
		      json.append(array2json((Object[]) obj));
		    } else if (obj instanceof List) {
		      json.append(list2json((List<?>) obj));
		    } else if (obj instanceof Map) {
		      json.append(map2json((Map<?, ?>) obj));
		    } else if (obj instanceof Set) {
		      json.append(set2json((Set<?>) obj));
		    } else {
		      json.append(bean2json(obj));
		    }
		    return json.toString();
		}
	 
	 public static String string2json(String s) {
		    if (s == null)
		      return "";
		    StringBuilder sb = new StringBuilder();
		    for (int i = 0; i < s.length(); i++) {
		      char ch = s.charAt(i);
		      switch (ch) {
		      case '"':
		        sb.append("\\\"");
		        break;
		      case '\\':
		        sb.append("\\\\");
		        break;
		      case '\b':
		        sb.append("\\b");
		        break;
		      case '\f':
		        sb.append("\\f");
		        break;
		      case '\n':
		        sb.append("\\n");
		        break;
		      case '\r':
		        sb.append("\\r");
		        break;
		      case '\t':
		        sb.append("\\t");
		        break;
		      case '/':
		        sb.append("\\/");
		        break;
		      default:
		        if (ch >= '\u0000' && ch <= '\u001F') {
		          String ss = Integer.toHexString(ch);
		          sb.append("\\u");
		          for (int k = 0; k < 4 - ss.length(); k++) {
		            sb.append('0');
		          }
		          sb.append(ss.toUpperCase());
		        } else {
		          sb.append(ch);
		        }
		      }
		    }
		    return sb.toString();
		}
	 
		public static String array2json(Object[] array) {
		    StringBuilder json = new StringBuilder();
		    json.append("[");
		    if (array != null && array.length > 0) {
		      for (Object obj : array) {
		        json.append(object2json(obj));
		        json.append(",");
		      }
		      json.setCharAt(json.length() - 1, ']');
		    } else {
		      json.append("]");
		    }
		    return json.toString();
		}
		
		public static String list2json(List<?> list) {
		    StringBuilder json = new StringBuilder();
		    json.append("[");
		    if (list != null && list.size() > 0) {
		      for (Object obj : list) {
		        json.append(object2json(obj));
		        json.append(",");
		      }
		      json.setCharAt(json.length() - 1, ']');
		    } else {
		      json.append("]");
		    }
		    return json.toString();
		}
		
		public static String map2json(Map<?, ?> map) {
		    StringBuilder json = new StringBuilder();
		    json.append("{");
		    if (map != null && map.size() > 0) {
//		      for (Object key : map.keySet()) {
//		        json.append(object2json(key));
//		        json.append(":");
//		        json.append(object2json(map.get(key)));
//		        json.append(",");
//		      }
		      for(Map.Entry me : map.entrySet()) {
		    	  json.append(object2json(me.getKey()));
			        json.append(":");
			        json.append(object2json(me.getValue()));
			        json.append(",");
		      } 	
		    	
		      json.setCharAt(json.length() - 1, '}');
		    } else {
		      json.append("}");
		    }
		    return json.toString();
		}
		
		public static String set2json(Set<?> set) {
		    StringBuilder json = new StringBuilder();
		    json.append("[");
		    if (set != null && set.size() > 0) {
		      for (Object obj : set) {
		        json.append(object2json(obj));
		        json.append(",");
		      }
		      json.setCharAt(json.length() - 1, ']');
		    } else {
		      json.append("]");
		    }
		    return json.toString();
		}
		
		public static String bean2json(Object bean) {
		    StringBuilder json = new StringBuilder();
		    json.append("{");
		    
		    PropertyDescriptor[] props = null;
		    
		    try {
		      props = Introspector.getBeanInfo(bean.getClass(), Object.class).getPropertyDescriptors();
		    } catch (IntrospectionException e) {
		        e.printStackTrace();
		    }
		    if (props != null) {
		      for (int i = 0; i < props.length; i++) {
		        try {
		          String name = object2json(props[i].getName());
		          String value = object2json(props[i].getReadMethod().invoke(bean));
		          json.append(name);
		          json.append(":");
		          json.append(value);
		          json.append(",");
		        } catch (Exception e) {
		            e.printStackTrace();
		        }
		      }
		      json.setCharAt(json.length() - 1, '}');
		    } else {
		      json.append("}");
		    }
		    return json.toString();
		}

}
